package com.wenlong.train_ticketing_system_springboot.querymodule.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wenlong.train_ticketing_system_springboot.querymodule.mapper.OrderMapper;
import com.wenlong.train_ticketing_system_springboot.querymodule.mapper.UserMapper;
import com.wenlong.train_ticketing_system_springboot.querymodule.pojo.Order;
import com.wenlong.train_ticketing_system_springboot.querymodule.pojo.Ticket;
import com.wenlong.train_ticketing_system_springboot.querymodule.pojo.User;
import com.wenlong.train_ticketing_system_springboot.querymodule.producter.RabbitProduct;
import com.wenlong.train_ticketing_system_springboot.querymodule.service.TicketService;
import com.wenlong.train_ticketing_system_springboot.querymodule.mapper.TicketMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 *
 */
@Service
public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket>
        implements TicketService {

    @Autowired
    private TicketMapper ticketMapper;
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitProduct rabbitProduct;

    @Override
    public Page<Ticket> getTicketByPages(Long cur, Long size) {
        Page<Ticket> page = new Page<>(cur, size);
        return ticketMapper.selectPage(page, null);
    }

    @Override
    public Page<Ticket> getTicketWithConditionByPages(Long cur, long size, String descrip, String price, String store, String departTime) {
        Page<Ticket> page = new Page<>(cur, size);
        if (departTime.length() > 4) {
            departTime = departTime.trim();
            departTime = departTime.substring(0, 5);
        }
        QueryWrapper<Ticket> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(descrip), "descrip", descrip)
                .eq(StringUtils.isNotBlank(price), "price", price)
                .eq(StringUtils.isNotBlank(store), "store", store)
                .like(StringUtils.isNotBlank(departTime) ,"depart_time", departTime);
        return ticketMapper.selectPage(page, queryWrapper);
    }

    @Override
    public /*synchronized*/ @Transactional
    Page<Ticket> createOrderWithTransactionIntoRedis(Long cur, Long size, Long id, Long uId) {
        Long key = IdWorker.getId();
        // 开启事务进行数据存入数据库
        try {
            // 更新票的数量
            Ticket ticket = ticketMapper.selectById(id);
            if(ticket.getStore() > 0) {
                ticket.setStore(ticket.getStore() - 1);
            }else {
                rabbitProduct.sendDelayMessageToNotify(100,"the Ticket have sell out");
                throw new RuntimeException("the Ticket have sell out");
            }
            ticketMapper.updateById(ticket);
            User user = userMapper.selectById(uId);
            // 创建订单
            Order order = new Order();
            order.setId(key);
            order.setTId(ticket.getId());
            order.setUId(uId);
            // 时间格式化
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            String format = simpleDateFormat.format(ticket.getDepartTime());
            order.setDescrip(ticket.getDescrip() + " " +
                    user.getUserName() + " " +
                    format + " " + ticket.getPrice());
//            int n  = 10 / 0; // 测试事务
            orderMapper.insert(order);
            // 提醒延迟
            rabbitProduct.sendDelayMessageToNotify(15000, "you have a order will be out of date, " +
                    "please pay for it as soon as possible!!");
            // 删除延时
            rabbitProduct.sendDelayMessageToDeleteMsg(30000, "" + key);
            // 设置在数据库中的时间
            redisTemplate.opsForValue().set("" + key, "the id of order", 5, TimeUnit.MINUTES);
        } catch (RuntimeException e) {
            rabbitProduct.sendDelayMessageToNotify(200,"the order have not create and do not deduct money");
//            e.printStackTrace();
            throw new RuntimeException(e);
            // 事务回退, 无法作用
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

        Page<Ticket> page = new Page<>(cur, size);
        return ticketMapper.selectPage(page, null);
    }

    @Override
    public @Transactional
    Page<Ticket> createOrderIntoMysql(Long cur, Long size, Long id, Long uId) {
        try {
            Ticket ticket = ticketMapper.selectById(id);
            ticket.setStore(ticket.getStore() - 1);
            ticketMapper.updateById(ticket);
            User user = userMapper.selectById(uId);
            // 生成订单
            Order order = new Order();
            order.setTId(ticket.getId());
            order.setUId(uId);
            // 时间格式化
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            String format = simpleDateFormat.format(ticket.getDepartTime());
            order.setDescrip(ticket.getDescrip() + " " +
                    user.getUserName() + " " +
                    format + " " + ticket.getPrice());
            /*模拟冲突
            int n  = 10 / 0;*/
            orderMapper.insert(order);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
            // 事务回退, 无法作用
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        Page<Ticket> page = new Page<>(cur, size);
        return ticketMapper.selectPage(page, null);
    }
}




